import { ref, onUnmounted, Ref, ComputedRef, watch, nextTick } from "vue";
import echarts from "./index";
import { EChartsType } from "echarts/core";
import * as echarts_types_dist_echarts from "echarts/types/dist/echarts";
import { ECharts, EChartsOption } from "echarts";
import { PolarComponent } from "echarts/components";
echarts.use([PolarComponent]);

type Theme = "light" | "dark" | "default";

export interface EchartOptions {
  /** 主题色（可选，默认`default`） */
  theme?: Ref<Theme> | ComputedRef<Theme>;
  /** 给`x`、`y`轴添加`Tooltip`文字提示的元素id，默认`tooltipElement` */
  tooltipId?: string;
  /** 设备像素比，默认取浏览器的值`window.devicePixelRatio` */
  devicePixelRatio?: number;
  /** 渲染模式，支持`canvas`或者`svg`，默认`canvas` */
  renderer?: "canvas" | "svg";
  /** 是否开启脏矩形渲染，只有在`Canvas`渲染模式有效，默认为`false` */
  useDirtyRect?: boolean;
  /** 是否扩大可点击元素的响应范围。`null`表示对移动设备开启；`true`表示总是开启；`false`表示总是不开启 */
  useCoarsePointer?: boolean;
  /** 扩大元素响应范围的像素大小，配合`opts.useCoarsePointer`使用 */
  pointerSize?: number;
  /** 是否使用服务端渲染，只有在`SVG`渲染模式有效。开启后不再会每帧自动渲染，必须要调用 [renderToSVGString](https://echarts.apache.org/zh/api.html#echartsInstance.renderToSVGString) 方法才能得到渲染后`SVG`字符串 */
  ssr?: boolean;
  /** 可显式指定实例宽度，单位为像素。如果传入值为`null/undefined/'auto'`，则表示自动取`dom`（实例容器）的宽度 */
  width?: number | string;
  /** 可显式指定实例高度，单位为像素。如果传入值为`null/undefined/'auto'`，则表示自动取`dom`（实例容器）的高度 */
  height?: number | string;
  /** 使用的语言，内置`ZH`和`EN`两个语言，也可以使用 [echarts.registerLocale](https://echarts.apache.org/zh/api.html#echarts.registerLocale) 方法注册新的语言包。目前支持的语言见 [src/i18n](https://github.com/apache/echarts/tree/release/src/i18n) */
  locale?: string;
}

interface UtilsEChartsOption extends EChartsOption {
  /** 清空当前实例，会移除实例中所有的组件和图表，一般用于动态渲染，默认：`true` */
  clear?: boolean;
  /** 给`x`、`y`轴添加`Tooltip`文字提示，一般用于文字太长，`x`代表`x轴`   `y`代表`y轴`   `true`(默认)代表`x、y轴`（该属性生效的前提是将 `xAxis` 或者 `yAxis` 添加`triggerEvent: true`属性，用到哪个添加哪个） */
  addTooltip?: ToolTipType;
  /** `window.onresize` 时改变图表尺寸的延时时间，单位毫秒，默认 `300` 毫秒。当您的 `echarts` 在拖拉窗口时不会自适应（一般不会出现这种情况），可以调整 `delay` 数值到自适应为止 */
  delay?: number;
  /** 是否监听页面`resize`事件并在页面`resize`时改变图表尺寸以适应当前容器，监听及改变，`true`(默认)代表监听 `false`代表不监听 */
  resize?: boolean;
}

declare type ElementEventType = "echarts" | "zrender";
declare type ElementEventName =
  | "click"
  | "dblclick"
  | "mousewheel"
  | "mouseout"
  | "mouseover"
  | "mouseup"
  | "mousedown"
  | "mousemove"
  | "contextmenu"
  | "drag"
  | "dragstart"
  | "dragend"
  | "dragenter"
  | "dragleave"
  | "dragover"
  | "drop"
  | "globalout"
  | "rendered";

interface OptionsParams {
  /** `echarts事件（默认）`、`zrender事件` */
  type?: ElementEventType;
  /** 事件类型名称 `必传` */
  name: ElementEventName;
  /** query属性 可选 */
  query?: string | Object;
  /** 回调函数，返回params参数 `必传` */
  callback: Fn;
}

interface LoadOpts {
  type?: string;
  opts?: {
    text?: string;
    color?: string;
    textColor?: string;
    maskColor?: string;
    zlevel?: number;
    /** 字体大小。从 `v4.8.0` 开始支持 */
    fontSize?: number;
    /** 是否显示旋转动画（spinner）。从 `v4.8.0` 开始支持 */
    showSpinner?: boolean;
    /** 旋转动画（spinner）的半径。从 `v4.8.0` 开始支持 */
    spinnerRadius?: number;
    /** 旋转动画（spinner）的线宽。从 `v4.8.0` 开始支持 */
    lineWidth?: number;
    /** 字体粗细。从 `v5.0.1` 开始支持 */
    fontWeight?: string;
    /** 字体风格。从 `v5.0.1` 开始支持 */
    fontStyle?: string;
    /** 字体系列。从 `v5.0.1` 开始支持 */
    fontFamily?: string;
  };
}
interface EchartGlobalProperties {
  /** 全局`property`属性名 */
  name?: string;
  /** 全局`property`属性值 */
  value?: ECharts;
}
interface AppendDataOpts {
  /** 要增加数据的系列序号 */
  seriesIndex?: string | number;
  /** 增加的数据 */
  data?: Array<any>;
}
interface DataURL {
  /** 导出的格式，可选 png, jpg, svg（注意：png, jpg 只有在 canvas 渲染器的时候可使用，svg 只有在使用 svg 渲染器的时候可用） */
  type?: string;
  /** 导出的图片分辨率比例，默认为 1 */
  pixelRatio?: number;
  /** 导出的图片背景色，默认使用 option 里的 backgroundColor */
  backgroundColor?: string;
  /** 忽略组件的列表，例如要忽略 toolbox 就是 ['toolbox'] */
  excludeComponents?: Array<string>;
}
type ToolTipType = "x" | "y" | true;
const configureEvents = (instance, events) => {
  events.forEach(event => {
    if (event?.type === "zrender") {
      instance.on(event.name, event.callback);
    } else {
      instance.on(event.name, params => {
        console.log(event.name, params);
      });
    }
  });
};
export const useECharts = (
  elRef: Ref<HTMLDivElement>,
  options?: EchartOptions
): {
  /** `ECharts`实例 */
  echarts: echarts_types_dist_echarts.ECharts;
  /** 根据配置项渲染`ECharts` */
  setOptions: (
    options: UtilsEChartsOption | any,
    ...params: OptionsParams[]
  ) => void;
  /** 显示加载动画 */
  showLoading: (params: LoadOpts) => void;
  /** 隐藏加载动画 */
  hideLoading: () => void;
  /** 清空当前`ECharts`实例，会移除实例中所有的组件和图表 */
  clear: () => void;
  /** 改变`ECharts`图表尺寸，使其自适应容器 */
  resize: () => void;
  /** 获取`ECharts`实例 */
  getInstance: () => echarts_types_dist_echarts.ECharts | null;
  /** 获取绑定到`echarts`的全局 [property](https://cn.vuejs.org/api/application.html#app-config-globalproperties) */
  getGlobalProperties: () => EchartGlobalProperties;
  /** 获取`ECharts`实例容器的`Dom`节点 */
  getDom: () => HTMLCanvasElement | HTMLDivElement;
  /** 获取`ECharts`实例容器的宽度 */
  getWidth: () => number;
  /** 获取`ECharts`实例容器的高度 */
  getHeight: () => number;
  /** 获取当前`ECharts`实例中维护的`option`对象 */
  getOption: () => echarts_types_dist_echarts.EChartsCoreOption;
  /** 此接口用于，在大数据量（百万以上）的渲染场景，分片加载数据和增量渲染 */
  appendData: (opts: AppendDataOpts) => void;
  /** 导出图表图片，返回一个`base64`的`URL`，可以设置为`Image`的`src` */
  getDataURL: (opts: DataURL) => string;
  /** 导出联动的图表图片，返回一个`base64`的`url`，可以设置为`Image`的`src`。导出图片中每个图表的相对位置跟容器的相对位置有关 */
  getConnectedDataURL: (opts: DataURL) => string;
  /**
   * @description 给`x`、`y`轴添加`Tooltip`文字提示
   * @param type `x`代表`x轴`   `y`代表`y轴`   `true`(默认)代表`x、y轴` （该属性生效的前提是将 `xAxis` 或者 `yAxis` 添加`triggerEvent: true`属性，用到哪个添加哪个）
   */
  addTooltip: (type: ToolTipType) => void;
} => {
  const echartsInstance = ref<EChartsType | null>(null);
  const tempParams = ref([]);
  const setOptions = (
    uOptions: UtilsEChartsOption,
    ...params: OptionsParams[]
  ) => {
    // params是点击方法
    tempParams.value = [uOptions, ...params];
  };

  watch([() => tempParams.value, () => echartsInstance.value], async () => {
    await nextTick();
    if (!elRef.value) return;
    setTimeout(() => {
      if (!echartsInstance.value) {
        echartsInstance.value = echarts.init(elRef.value, options.theme.value);
        echartsInstance.value.resize();
      }

      // 注册参数
      echartsInstance.value.setOption(tempParams.value[0]);
      // 监听方法
      configureEvents(echartsInstance.value, tempParams.value.slice(1));
    });
  });
  // 监听主题切换
  watch(
    () => options.theme,
    () => {
      echartsInstance.value = echarts.init(elRef.value, options.theme.value);
    }
  );
  const showLoading = (params: LoadOpts) => {
    if (echartsInstance.value) {
      echartsInstance.value.showLoading(params);
    }
  };

  const hideLoading = () => {
    if (echartsInstance.value) {
      echartsInstance.value.hideLoading();
    }
  };

  const clear = () => {
    if (echartsInstance.value) {
      echartsInstance.value.clear();
    }
  };

  const resize = (opts?: any) => {
    if (echartsInstance.value) {
      echartsInstance.value.resize(opts);
    }
  };

  const getInstance = () => {
    return echartsInstance.value;
  };
  onUnmounted(() => {
    if (echartsInstance.value) {
      echartsInstance.value.dispose();
      echartsInstance.value = null;
    }
  });

  return {
    echarts: echartsInstance.value,
    setOptions,
    showLoading,
    hideLoading,
    clear,
    resize,
    getInstance
  };
};
